package com.rw.tool.util.io.file.wrapper;

import com.rw.tool.util.io.file.exception.LambdaParseException;
import lombok.Getter;

import java.lang.invoke.SerializedLambda;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Locale;

/**
 * Lambda查询条件
 */
@Getter
public class FileLambdaQueryWrapper<T> extends FileQueryWrapper {
    // 反射的方法名
    private static final String METHOD = "writeReplace";

    // get属性的前缀
    private static final String GETTER_PREFIX = "get";

    /**
     * 加入自定义条件
     *
     * @param condition 条件
     */
    public FileLambdaQueryWrapper<T> addCondition(QueryCondition condition) {
        super.addCondition(condition);
        return this;
    }

    /**
     * 等于
     */
    public FileQueryWrapper eq(LambdaGetter<T> lambdaGetter, Object value) {
        super.eq(parseLambdaName(lambdaGetter), value);
        return this;
    }


    /**
     * 大于
     */
    public FileQueryWrapper gt(LambdaGetter<T> lambdaGetter, Object value) {
        super.gt(parseLambdaName(lambdaGetter), value);
        return this;
    }


    /**
     * 大于等于
     */
    public FileQueryWrapper ge(LambdaGetter<T> lambdaGetter, Object value) {
        super.ge(parseLambdaName(lambdaGetter), value);
        return this;
    }

    /**
     * 小于
     */
    public FileQueryWrapper lt(LambdaGetter<T> lambdaGetter, Object value) {
        super.lt(parseLambdaName(lambdaGetter), value);
        return this;
    }

    /**
     * 小于等于
     */
    public FileQueryWrapper le(LambdaGetter<T> lambdaGetter, Object value) {
        super.le(parseLambdaName(lambdaGetter), value);
        return this;
    }

    /**
     * 模糊查询
     */
    public FileQueryWrapper like(LambdaGetter<T> lambdaGetter, Object value) {
        super.like(parseLambdaName(lambdaGetter), value);
        return this;
    }

    /**
     * 获得条件
     *
     * @param lambdaGetter 字段lambda表达式
     * @return 条件
     */
    public QueryCondition getCondition(LambdaGetter<T> lambdaGetter) {
        return getCondition(parseLambdaName(lambdaGetter));
    }

    /**
     * 获得等于条件
     *
     * @param lambdaGetter 字段lambda表达式
     * @return 条件
     */
    public Object getEQValue(LambdaGetter<T> lambdaGetter) {
        return getEQValue(parseLambdaName(lambdaGetter));
    }

    /**
     * 让lambda表达式变为属性名
     *
     * @param lambdaGetter lambda表达式
     * @return 属性名
     */
    public static <T> String parseLambdaName(LambdaGetter<T> lambdaGetter) {
        try {
            Method method = lambdaGetter.getClass().getDeclaredMethod(METHOD);
            method.setAccessible(true);
            String methodName = ((SerializedLambda) method.invoke(lambdaGetter)).getImplMethodName();
            return subGetterName(methodName);
        } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
            throw new LambdaParseException(e);
        }
    }

    /**
     * 把getXxx和isXxx变为XXX格式
     *
     * @return 属性名
     */
    private static String subGetterName(String getterName) {
        String propName;

        // 去除属性名的is或者getter开头
        if (getterName.startsWith("is")) {
            propName = getterName.substring(2);
        } else if (getterName.startsWith("get")) {
            propName = getterName.substring(3);
        } else {
            String errorMsg = "property method can only start with 'id' or 'get'!";
            throw new LambdaParseException(errorMsg);
        }

        // 将首字母小写
        if (propName.length() > 1) {
            return Character.toLowerCase(propName.charAt(0)) + propName.substring(1);
        } else {
            return propName.toLowerCase(Locale.ROOT);
        }
    }
}
